//
//  SETextView.swift
//  SmartEyeForPatient
//
//  Created by QDSG on 2021/4/6.
//

import UIKit

@objc protocol SETextViewDelegate: NSObjectProtocol {
   @objc optional func textViewShouldBeginEditing(_ textView: UITextView) -> Bool
    
   @objc optional func textViewShouldEndEditing(_ textView: UITextView) -> Bool
   
   @objc optional func textViewDidBeginEditing(_ textView: UITextView)
   
   @objc optional func textViewDidEndEditing(_ textView: UITextView)
   
   
   @objc optional func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
   
   @objc optional func textViewDidChange(_ textView: UITextView)
   
   @objc optional func textViewDidChangeSelection(_ textView: UITextView)
   
   @objc optional func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool
}

class SETextView: UITextView {

    weak var tvDelegate: SETextViewDelegate?

    /// 占位字符颜色
    var placeholderColor: UIColor = Asset.textGrayLightest.color { didSet { setNeedsLayout() } }
    
    /// 占位字符
    var placeholder: String = "" { didSet { setNeedsLayout() } }
    
    /// 文字最小字数, 默认 0
    var minNumberOfWords: Int = 0 { didSet { setNeedsLayout() } }
    
    /// 文字最大字数, 默认 300
    var maxNumberOfWords: Int = 300 { didSet { setNeedsLayout() } }
    
    var showTextCountView: Bool = true { didSet { setNeedsLayout() } }
    
    var textLayer: CATextLayer!
    
    var countTextLayer: CATextLayer!
    
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        delegate = self
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        delegate = self
    }
}

extension SETextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        
        if textLayer == nil {
            textLayer = CATextLayer()
            textLayer.contentsScale = UIScreen.main.scale
            textLayer.alignmentMode = .left
            textLayer.backgroundColor = UIColor.clear.cgColor
            textLayer.foregroundColor = placeholderColor.cgColor
            textLayer.font = font
            textLayer.fontSize = font!.pointSize
            textLayer.string = placeholder
            textLayer.frame = CGRect(origin: CGPoint(x: 5, y: bounds.minY + 8), size: CGSize(width: bounds.size.width - 10, height: bounds.size.height - 16))
            textLayer.isWrapped = true
            
            layer.insertSublayer(textLayer, at: 0)
        }
        
        if showTextCountView {
            if countTextLayer == nil {
                countTextLayer = CATextLayer()
                countTextLayer.contentsScale = UIScreen.main.scale
                countTextLayer.alignmentMode = .right
                countTextLayer.backgroundColor = UIColor.clear.cgColor
                countTextLayer.foregroundColor = placeholderColor.cgColor
                countTextLayer.font = font
                countTextLayer.fontSize = font!.pointSize
                
                let tempLabel = UILabel()
                let tempText = "\(maxNumberOfWords)/\(maxNumberOfWords)"
                tempLabel.text = tempText
                tempLabel.font = font
                tempLabel.sizeToFit()
                
                countTextLayer.frame = tempLabel.frame
                countTextLayer.string = "\(minNumberOfWords)/\(maxNumberOfWords)"
                layer.addSublayer(countTextLayer)
            }
            
            countTextLayer.frame.origin = CGPoint(x: bounds.size.width - countTextLayer.bounds.size.width, y: bounds.size.height - countTextLayer.bounds.size.height + contentOffset.y)
        }
        
        delegate!.textViewDidChange!(self)
    }
}

extension SETextView: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        if showTextCountView {
            countTextLayer.string = "\(text.count)/\(maxNumberOfWords)"
        }
        textLayer.isHidden = text.count > 0
        
        if let delegate = tvDelegate, delegate.responds(to: #selector(textViewDidChange(_:)))  {
            delegate.textViewDidChange!(textView)
        }
    }
    
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        if text.isEmoji || text.containsEmoji {
            let other = "➋➌➍➎➏➐➑➒"
            if (other as NSString).range(of: text).location != NSNotFound {
                return true
            }
            return false
        }
        
        if textView.textInputMode?.primaryLanguage == "emoji" ||
            textView.textInputMode?.primaryLanguage == nil {
            return false
        }
        
        var result: Bool = true
        let oldText = textView.text as NSString
        let newText = oldText.replacingCharacters(in: range, with: text)
        
        if let delegate = tvDelegate, delegate.responds(to: #selector(textView(_:shouldChangeTextIn:replacementText:))) {
            result = delegate.textView!(textView, shouldChangeTextIn: range, replacementText: text)
        }
        
        guard showTextCountView == true else { return result }
        
        return newText.count > maxNumberOfWords ? false : result
    }
    
    func textViewDidEndEditing(_ textView: UITextView) {
        if let delegate = tvDelegate, delegate.responds(to: #selector(textViewDidEndEditing(_:))) {
            delegate.textViewDidEndEditing!(textView)
        }
    }
}

extension String {
    /// 判断是不是Emoji
    ///
    /// - Returns: true false
    var containsEmoji: Bool {
        for scalar in unicodeScalars {
            switch scalar.value {
            case 0x1F600...0x1F64F,
                 0x1F300...0x1F5FF,
                 0x1F680...0x1F6FF,
                 0x2600...0x26FF,
                 0x2700...0x27BF,
                 0xFE00...0xFE0F:
                return true
            default:
                continue
            }
        }
        return false
    }

    /// 判断是不是Emoji
    ///
    /// - Returns: true false
    var isEmoji: Bool {
        let pattern = "[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]"
        let pred = NSPredicate(format: "SELF MATCHES %@",pattern)
        return pred.evaluate(with: self)
    }
}
